﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Diagnostics;

using Excel = Microsoft.Office.Interop.Excel;
using System.Reflection;

namespace cimdict
{
    class ExportExcel
    {
        private Excel.Application oXL;
        private Excel._Workbook oWB;
        private Excel._Worksheet oSheet;
        //private Excel.Range oRng;

        private int row = 1;
        private int col = 1;

        private int tabrow = 0;
        private int tabcol = 0;

        private string defclass = "";

        public void println(string str)
        {
            oSheet.Cells[this.row, this.col] = str;
            this.row++;
            this.col = 1;
        }

        public void print(string str)
        {
            oSheet.Cells[this.row, this.col] = str;
            this.col++;

        }

        public void style(int merge, bool border, bool center, bool bold)
        {
            Excel.Range range = oSheet.get_Range(oSheet.Cells[this.row, this.col], oSheet.Cells[this.row, this.col + merge]);

            if (merge > 0)
            {
                range.Merge(true);
            }

            if (center)
            {
                range.HorizontalAlignment = Excel.XlHAlign.xlHAlignCenter;
            }

            if (border)
            {
                range.BorderAround(Missing.Value, Excel.XlBorderWeight.xlThin, Excel.XlColorIndex.xlColorIndexAutomatic, Missing.Value);
            }

            if (bold)
            {
                range.Font.Bold = true;
            }
        }

        public void over()
        {
            oXL.Visible = true;
            oXL.UserControl = true;
        }

        public ExportExcel()
        {
            try
            {
                //Start Excel and get Application object.
                oXL = new Excel.Application();
                oXL.Visible = true;

                //Get a new workbook.
                oWB = (Excel._Workbook)(oXL.Workbooks.Add(Missing.Value));
                oSheet = (Excel._Worksheet)oWB.ActiveSheet;
            }
            catch (Exception theException)
            {
                Console.WriteLine(theException.Message);
            }
        }

        public void printClass(string className, bool subClass)
        {
            foreach (CIMClass cimc in CIMRepo.getAllClasses())
            {
                if (cimc.name == className)
                {
                    if (subClass)
                    {
                        this.style(1, true, true, false);
                        if (ExportFilter.check(this.defclass.Trim(), ""))
                        {
                            this.println(cimc.name);
                        }
                        else
                        {
                            foreach (CIMProp prop in cimc.props)
                            {
                                if (ExportFilter.check(this.defclass.Trim(), prop.name.Trim()))
                                {
                                    this.println(cimc.name);
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        this.style(1, false, true, false);
                        this.defclass = className;
                        this.println(cimc.name);
                    }

                    if ((cimc.desc != "") && (!subClass))
                    {
                        this.style(1, false, false, false);
                        this.println(cimc.desc);
                    }

                    if (!subClass)
                    {
                        //Print header
                        this.tabrow = this.row;
                        this.tabcol = this.col;

                        this.style(0, true, false, true);
                        this.print("Property Name");

                        this.style(0, true, false, true);
                        this.println("Property Implemetation");

                        Excel.Range range1 = oSheet.get_Range(oSheet.Cells[this.tabrow, this.tabcol], oSheet.Cells[this.tabrow, this.tabcol + 1]);
                        range1.Font.Bold = true;
                    }

                    foreach (CIMProp prop in cimc.props)
                    {
                        if (ExportFilter.check(this.defclass.Trim(), prop.name.Trim()))
                        {
                            this.style(0, true, false, false);
                            this.print(prop.name);

                            this.style(0, true, false, false);
                            this.println(prop.desc);
                        }
                    }

                    if (cimc.baseName != "")
                    {
                        this.printClass(cimc.baseName, true);
                    }
                    break;
                }
            }
        }

    }

    class ExportFilter
    {
        private ExportFilter()
        { }

        private static List<string> printList = new List<string>();

        public static void add(string str)
        {
            printList.Add(str);
        }

        public static bool check(string cls, string propDesc)
        {
            if (printList.IndexOf(cls + ".*") >= 0) return true;
            foreach (string fullname in printList)
            {
                if (fullname.IndexOf(cls) >= 0)
                {
                    string[] parts = fullname.Split('.');
                    if (parts.Length > 1)
                    {
                        if (propDesc.Equals(parts[1]))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
    }

}
